package org.chen.spring.aop.factory;

import org.chen.spring.aop.annotation.After;
import org.chen.spring.aop.annotation.AfterThrowing;
import org.chen.spring.aop.annotation.Around;
import org.chen.spring.aop.annotation.Before;
import org.chen.spring.aop.processor.ChenAopBeanPostProcessor;
import org.chen.spring.core.factory.BeanFactory;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 切面工厂
 *
 * @author Chen
 * @since 2023/6/8 15:23
 */

public class AspectFactory {

    /**
     * AOP切面Map k->切面注解 v->(k->AOP注解名 v->切面方法)
     */
    private static final ConcurrentHashMap<Annotation, Map<String, Method>> ASPECT_MAP = new ConcurrentHashMap<>();

    public static void registerAspect(Class<?> clazz) {
        for (Method method : clazz.getDeclaredMethods()) {
            for (Annotation annotation : method.getDeclaredAnnotations()) {
                Class<? extends Annotation> type = annotation.annotationType();
                if (type != Around.class && type != Before.class && type != After.class && type != AfterThrowing.class) {
                    continue;
                }
                String value = "";
                if (type == Around.class) {
                    value = ((Around) annotation).value();
                } else if (type == Before.class) {
                    value = ((Before) annotation).value();
                } else if (type == After.class) {
                    value = ((After) annotation).value();
                } else {
                    value = ((AfterThrowing) annotation).value();
                }
                Map<String, Method> methodMap = ASPECT_MAP.getOrDefault(annotation, new ConcurrentHashMap<>());
                value = value.substring(value.indexOf("(") + 1, value.indexOf(")"));
                //获取出AOP注解名
                value = value.substring(value.lastIndexOf(".") + 1);
                methodMap.put(value, method);
                ASPECT_MAP.put(annotation, methodMap);
            }

        }
    }

    public static ConcurrentHashMap<Annotation, Map<String, Method>> getAspectMap() {
        return ASPECT_MAP;
    }

    /**
     * 初始化切面
     */
    public void initAspect(Class<?> clazz) {
        //注册AOP切面后处理器
        BeanFactory.registerBeanPostProcessors(new ChenAopBeanPostProcessor());

        //注册切面扫描
        BeanFactory.resisterScanBean(new AspectScanBean(clazz.getPackageName()));
    }
}
